﻿package com.danielsheldon.effects.particles 
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.getTimer;
	import flash.utils.Timer;
	
	/**
	 * ...
	 * @author Daniel Sheldon
	 */
	public class Emitter extends Sprite
	{
		private var _speed:Number = 60;
		private var _target:DisplayObject;
		private var _density:int = 1;
		private var _maxParticles:int = 10000;
		private var _duration:int = 1;
		private var _coverage:Number = Math.PI * 2;
		private var _startRotation:Number = 0;
		private var _particle:Class;
		private var _myTimer:Timer = new Timer(17);
		private var _numOfCreated:int = 0;
		private var _myParticles:Vector.<IParticle> = new Vector.<IParticle>();
		
		public function get target():DisplayObject { return _target; }
		
		public function get density():int { return _density; }
		public function set density(value:int):void 
		{
			_density = value;
		}
		
		public function get maxParticles():int { return _maxParticles; }
		public function set maxParticles(value:int):void 
		{
			_maxParticles = value;
		}
		
		public function get duration():int { return _duration; }
		public function set duration(value:int):void 
		{
			_duration = value;
		}
		
		public function get coverage():Number { return _coverage; }
		public function set coverage(value:Number):void 
		{
			_coverage = value;
		}
		
		public function get startRotation():Number { return _startRotation; }
		public function set startRotation(value:Number):void 
		{
			_startRotation = value;
		}
		
		public function get particle():Class { return _particle; }
		public function set particle(value:Class):void 
		{
			_particle = value;
		}
		
		public function get numOfCreated():int { return _numOfCreated; }
		
		public function Emitter(particle:Class) 
		{
			_particle = particle;
			_myTimer.addEventListener(TimerEvent.TIMER, frameUpdate);
			//_myTimer.addEventListener(TimerEvent.TIMER, update);
		}
		
		public function start():void
		{
			_myTimer.start();
		}
		
		public function pause():void
		{
			_myTimer.stop();
		}
		
		public function resume():void 
		{
			_myTimer.start();
			lastTime = getTimer();
		}
		
		public function update(e:TimerEvent = null):void 
		{
			addParticles();
			moveParticles();
		}
		
		private function moveParticles():void
		{
			for each(var particle:IParticle in _myParticles)
			{
				//particle.x += particle.cos * 3;
				//particle.y += particle.sin * 3;
				
				particle.x += particle.cos * (_speed * deltaTime/1000);
				particle.y += particle.sin * (_speed * deltaTime / 1000);
				particle.lifeLived += deltaTime;
				
			}
		}
		
		private function addParticles():void
		{
			var emitted:int = 0;
			
			while (_numOfCreated < maxParticles && emitted < density)
			{
				var newParticle:IParticle = new _particle();
				_myParticles.push(newParticle);
				
				var angle:Number = Math.random() * _coverage + rotation;
				newParticle.sin = Math.sin(angle);
				newParticle.cos = Math.cos(angle);				
				
				addChild(newParticle as DisplayObject);
				
				emitted++;
				_numOfCreated++;
			}
		}
		
		private var lastTime:uint;
		private var deltaTime:uint;
		
		private function frameUpdate(event:TimerEvent):void 
		{
			deltaTime = getTimer() - lastTime;
			lastTime = getTimer();
			
			update();			
		}
		
		public function particleDead(particle:IParticle):void
		{
			for (var i:uint = 0; i < _myParticles.length; i++)
			{
				if (_myParticles[i] == particle)
				{
					_myParticles.splice(i, 1);
					//trace("particle killed");
					break;
				}
			}
			
			removeChild(particle as DisplayObject);
		}
		
		
		/*
		private var mAccumulator :Number = 0;
		private var mTime:Number = 0;
		
		private function frameUpdate(event:TimerEvent)
        {			
            mAccumulator += (getTimer() - mTime);  //this accumulator gets the time passed since last update
            var deltaTime:uint = 17;    //my static delta time
            mTime = getTimer();    //get the current time on THIS frame

            while(mAccumulator >= deltaTime)    //the update loop, runs until we've "caught up" 
            {
				update()
                mAccumulator -= deltaTime;
            }
			
			event.updateAfterEvent();
            //trace("framewatcher now done ticking all objects.  see you next time!");
        }
		*/
		
	}
	
}